00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef _THANDLE_H
00029 #define _THANDLE_H
00030
00031 #include <assert.H>
00032
00033 #ifndef _VECTOR_
00034 #include <vector>
00035 #endif
00036
00037 #pragma warning( disable : 4786 )
00038 #pragma warning( disable : 4285 )
00039
00040 #define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
00041 #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }
00042 #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
00043
00044 typedef unsigned long DWORD;
00045
00046 enum EraseType
00047 {
00048 ERASE_UNKNOWN,
00049 ERASE_NORMAL,
00050 ERASE_DELETE,
00051 ERASE_DELETE_ARRAY,
00052 ERASE_RELEASE
00053 };
00054
00055
00056
00057
00058 template <typename DATA, typename HANDLE>
00059 class THandleMgr
00060 {
00061 public:
00062
00063
00064 typedef std::vector <DATA> DataVec;
00065 typedef std::vector <unsigned int> MagicVec;
00066 typedef std::vector <unsigned int> FreeVec;
00067 typedef std::vector <int> RefVec;
00068
00069
00070
00071 THandleMgr( void ) { assert(!m_Singleton);
00072 m_Singleton = this;
00073 m_EraseType = ERASE_UNKNOWN; }
00074
00075 ~THandleMgr( void ) { EraseEntries(); m_Singleton = NULL; }
00076
00077 DATA * GetDataAt(int Index) { return (m_UserData.begin() + Index); }
00078 void SetEraseMethod( EraseType pType ) { assert(pType != ERASE_UNKNOWN); m_EraseType = pType; }
00079 unsigned int GetUsedHandleCount( void ) const { return ( m_MagicNumbers.size() - m_FreeSlots.size() ); }
00080 bool HasUsedHandles( void ) const { return ( !!GetUsedHandleCount() ); }
00081
00082
00083
00084
00085
00086
00087
00088 int AddReference( HANDLE& pHandle )
00089 {
00090 if( !pHandle.IsNull() )
00091 {
00092 unsigned int index = pHandle.GetIndex();
00093
00094 if( (index < m_UserData.size()) ||
00095 (m_MagicNumbers[ index ] == pHandle.GetMagic()) )
00096 {
00097 int& count = m_References[index];
00098 return count++;
00099 }
00100 else
00101 return -1;
00102 }
00103 else
00104 return -1;
00105 }
00106
00107
00108
00109
00110
00111
00112
00113
00114 int ReleaseReference( HANDLE& pHandle )
00115 {
00116 if( !pHandle.IsNull() )
00117 {
00118 unsigned int index = pHandle.GetIndex();
00119 int& count = m_References[index];
00120
00121 if( (index < m_UserData.size()) ||
00122 (m_MagicNumbers[ index ] == pHandle.GetMagic()) )
00123 {
00124 count--;
00125 if( count == 0 )
00126 {
00127 Release(pHandle);
00128 pHandle = HANDLE();
00129 m_References[index] = -1;
00130 return 0;
00131 }
00132 else
00133 return count;
00134 }
00135 else
00136 return -1;
00137 }
00138 else
00139 return -1;
00140 }
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 DATA* Acquire( HANDLE& handle )
00151 {
00152 assert( !handle.IsNull() );
00153
00154
00155
00156 unsigned int index;
00157 if ( m_FreeSlots.empty() )
00158 {
00159 index = m_MagicNumbers.size();
00160 handle.Init( index );
00161 m_UserData.push_back( DATA() );
00162 m_References.push_back(1);
00163 m_MagicNumbers.push_back( handle.GetMagic() );
00164 }
00165 else
00166 {
00167 index = m_FreeSlots.back();
00168 handle.Init( index );
00169 m_References[ index ] = 1;
00170 m_FreeSlots.pop_back();
00171 m_MagicNumbers[ index ] = handle.GetMagic();
00172 }
00173 return ( m_UserData.begin() + index );
00174 }
00175
00176
00177
00178
00179
00180
00181
00182 DATA * AddItem( HANDLE& handle, const DATA& data )
00183 {
00184 bool bOK = false;
00185
00186
00187 unsigned int index;
00188 if ( m_FreeSlots.empty() )
00189 {
00190 index = m_MagicNumbers.size();
00191 handle.Init( index );
00192 m_UserData.push_back( data );
00193 m_References.push_back(1);
00194 m_MagicNumbers.push_back( handle.GetMagic() );
00195 bOK = true;
00196 }
00197 else
00198 {
00199 index = m_FreeSlots.back();
00200 handle.Init( index );
00201 m_FreeSlots.pop_back();
00202 m_References[ index ] = 1;
00203 m_MagicNumbers[ index ] = handle.GetMagic();
00204 m_UserData[ index ] = data;
00205 bOK = true;
00206 }
00207
00208 m_References[index] = 1;
00209
00210 return ( m_UserData.begin() + index );
00211 }
00212
00213
00214
00215
00216 void Release( HANDLE& handle )
00217 {
00218
00219 unsigned int index = handle.GetIndex();
00220
00221 if( handle.IsNull() )
00222 return;
00223
00224
00225 if( (index < m_UserData.size()) ||
00226 (m_MagicNumbers[ index ] == handle.GetMagic()) )
00227 {
00228 assert( m_EraseType != ERASE_UNKNOWN );
00229
00230
00231 m_MagicNumbers[ index ] = 0;
00232 m_References[ index ] = -1;
00233 m_FreeSlots.push_back( index );
00234 handle = HANDLE();
00235
00236
00237 switch( m_EraseType )
00238 {
00239 case ERASE_DELETE:
00240
00241 assert(false);
00242 break;
00243
00244 case ERASE_DELETE_ARRAY:
00245
00246 assert(false);
00247 break;
00248
00249 case ERASE_RELEASE:
00250 assert(false);
00251 break;
00252 }
00253 }
00254 else
00255 {
00256 assert( false );
00257 }
00258 }
00259
00260
00261
00262
00263
00264
00265 DATA * GetData( HANDLE handle )
00266 {
00267 assert( !handle.IsNull() );
00268
00269 if ( handle.IsNull() ) return ( 0 );
00270
00271 unsigned int index = handle.GetIndex();
00272
00273 #if _DEBUG
00274
00275
00276 if ( ( index >= m_UserData.size() )
00277 || ( m_MagicNumbers[ index ] != handle.GetMagic() ) )
00278 {
00279
00280 return ( 0 );
00281 }
00282 #endif
00283
00284 return ( m_UserData.begin() + index );
00285 }
00286
00287
00288
00289
00290
00291
00292 const DATA* GetData( HANDLE handle ) const
00293 {
00294
00295 return ( const_cast<THandleMgr<DATA, HANDLE>*> ( this )->GetData( handle ) );
00296 }
00297
00298
00299
00300
00301 void EraseEntries(void)
00302 {
00303 int i = 0;
00304 int cnt = m_UserData.size();
00305
00306 assert( m_EraseType != ERASE_UNKNOWN );
00307
00308 switch( m_EraseType )
00309 {
00310 case ERASE_DELETE:
00311
00312
00313 assert(false);
00314 break;
00315
00316 case ERASE_DELETE_ARRAY:
00317
00318
00319 assert(false);
00320 break;
00321
00322 case ERASE_RELEASE:
00323
00324
00325 assert(false);
00326 break;
00327 }
00328
00329 m_UserData.clear();
00330 m_MagicNumbers.clear();
00331 m_FreeSlots.clear();
00332 m_References.clear();
00333 }
00334
00335 static THandleMgr<DATA, HANDLE> * GetHandleMgr(void) {
00336 return m_Singleton; }
00337
00338 protected:
00339
00340 EraseType m_EraseType;
00341 DataVec m_UserData;
00342 MagicVec m_MagicNumbers;
00343 FreeVec m_FreeSlots;
00344 RefVec m_References;
00345
00346 static THandleMgr<DATA, HANDLE> * m_Singleton;
00347 };
00348
00349
00350
00351
00352
00353
00354
00355
00356 template <typename TAG>
00357 class THandle
00358 {
00359 private:
00360 union
00361 {
00362 enum
00363 {
00364
00365 MAX_BITS_INDEX = 16,
00366 MAX_BITS_MAGIC = 16,
00367
00368
00369 MAX_INDEX = ( 1 << MAX_BITS_INDEX) - 1,
00370 MAX_MAGIC = ( 1 << MAX_BITS_MAGIC) - 1,
00371 };
00372
00373 struct
00374 {
00375 unsigned m_Index : MAX_BITS_INDEX;
00376 unsigned m_Magic : MAX_BITS_MAGIC;
00377 };
00378 unsigned long m_Handle;
00379 };
00380
00381 typedef THandleMgr< TAG, THandle<TAG> > ThisMgrType;
00382 typedef THandle<TAG> ThisType;
00383
00384 public:
00385
00386 THandle (void) : m_Handle( 0 ) { }
00387 ~THandle(void)
00388 {
00389 m_Handle = 0;
00390 }
00391
00392
00393
00394
00395
00396 void Init( unsigned int index )
00397 {
00398 assert( IsNull() );
00399 assert( index <= MAX_INDEX );
00400
00401 static unsigned int s_AutoMagic = 0;
00402 if ( ++s_AutoMagic > MAX_MAGIC )
00403 {
00404 s_AutoMagic = 1;
00405 }
00406
00407 m_Index = index;
00408 m_Magic = s_AutoMagic;
00409 }
00410
00411 unsigned int GetIndex ( void ) const { return ( m_Index ); }
00412 unsigned int GetMagic ( void ) const { return ( m_Magic ); }
00413 unsigned long GetHandle( void ) const { return ( m_Handle ); }
00414 TAG * GetData ( void ) const { return ( (ThisMgrType::GetHandleMgr()->GetData( *this ))); }
00415 bool IsNull ( void ) const { return ( !m_Handle ); }
00416
00417 operator unsigned int ( void ) const { return ( m_Handle ); }
00418
00419 THandle<TAG>& operator = ( const THandle<TAG>& r )
00420 {
00421 m_Handle = r.m_Handle;
00422 return *this;
00423 }
00424
00425 THandle<TAG>& operator = ( const DWORD& r )
00426 {
00427 m_Handle = r;
00428 return *this;
00429 }
00430
00431
00432 friend bool operator != ( const THandle<TAG>& l, const THandle<TAG>& r )
00433 { return ( l.m_Handle != r.m_Handle ); }
00434
00435 friend bool operator == ( const THandle<TAG>& l, const THandle<TAG>& r )
00436 { return ( l.m_Handle == r.m_Handle ); }
00437
00438 friend bool operator != ( const DWORD& l, const THandle<TAG>& r )
00439 { return ( l != r.m_Handle ); }
00440
00441 friend bool operator == ( const DWORD& l, const THandle<TAG>& r )
00442 { return ( l == r.m_Handle ); }
00443
00444 friend bool operator != ( const THandle<TAG>& l, const DWORD& r )
00445 { return ( l.m_Handle != r ); }
00446
00447 friend bool operator == ( const THandle<TAG>& l, const DWORD& r )
00448 { return ( l.m_Handle == r ); }
00449 };
00450
00451 #endif